package com.andy.drools.config;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;

import com.andy.drools.model.RuleConfig;
import com.andy.drools.model.vo.RuleVo;
import com.andy.drools.service.RuleConfigService;
import com.andy.drools.utils.DroolsUtils;

@Component
@Configuration
public class DroolsAutoConfiguration implements ApplicationRunner {

	private static final String RULES_PATH = "rules/";

	@Autowired
	private RuleConfigService ruleConfigService;

	// 装配多个规则库
	public Map<String, KieContainer> getMapKieContainer() throws IOException {
		Map<String, KieContainer> kieContainerMap = new HashMap<String, KieContainer>();
		// 查找数据库对应的规则库，进行加载
		List<RuleConfig> ruleConfigs = ruleConfigService.selectRuleConfigList(null);

		for (RuleConfig ruleConfig : ruleConfigs) {
			RuleVo ruleVo = new RuleVo();
			ruleVo.setForeignKey(ruleConfig.getRuleKey());
			List<RuleVo> ruleVos = ruleConfigService.selectRuleVoList(ruleVo);

			KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
			for (RuleVo rule : ruleVos) {
				String drl = rule.getContent();
				kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", drl);
			}

			final KieRepository kieRepository = getKieServices().getRepository();

			kieRepository.addKieModule(new KieModule() {
				public ReleaseId getReleaseId() {
					return kieRepository.getDefaultReleaseId();
				}
			});

			KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem(ruleVos));
			kieBuilder.buildAll();

			KieContainer kieContainer = getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());

			// DroolsRulesService.kieContainer = kieContainer;
			kieContainerMap.put(ruleConfig.getRuleKey(), kieContainer);
			// 存放在工具类中，方便使用
			DroolsUtils.kieContainerMap = kieContainerMap;
		}
		return kieContainerMap;
	}

	public KieFileSystem kieFileSystem(List<RuleVo> ruleVos) throws IOException {
		KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
//        for (Resource file : getRuleFiles()) {
//            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
//        }

		for (RuleVo rule : ruleVos) {
			String drl = rule.getContent();
			kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", drl);
		}

		return kieFileSystem;
	}

	private Resource[] getRuleFiles() throws IOException {
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
	}

	public KieContainer kieContainer(List<RuleVo> ruleVos) throws IOException {
		final KieRepository kieRepository = getKieServices().getRepository();

		kieRepository.addKieModule(new KieModule() {
			public ReleaseId getReleaseId() {
				return kieRepository.getDefaultReleaseId();
			}
		});

		KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem(ruleVos));
		kieBuilder.buildAll();

		KieContainer kieContainer = getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());

		return kieContainer;
	}

	private KieServices getKieServices() {
		return KieServices.Factory.get();
	}

	public KieBase kieBase(List<RuleVo> ruleVos) throws IOException {
		return kieContainer(ruleVos).getKieBase();
	}

	public KieSession kieSession(List<RuleVo> ruleVos) throws IOException {
		return kieContainer(ruleVos).newKieSession();
	}

	public KModuleBeanFactoryPostProcessor kiePostProcessor() {
		return new KModuleBeanFactoryPostProcessor();
	}

	public void run(ApplicationArguments args) throws Exception {
		System.out.println("初始化规则引擎......");
		// 这个是初始化一套规则,直接查所有drl
		List<RuleVo> ruleVos = ruleConfigService.selectRuleVoList(null);
		KieContainer kieContainer = kieContainer(ruleVos);
		DroolsUtils.kieContainer = kieContainer;

		// 这个是初始化多套规则,查找分好类的drl
		getMapKieContainer();
		System.out.println("规则引擎装配成功......");
	}

}
